/**
 * 检查response访问是否成功
 * @param response
 * @returns
 */
function checkStatus(response: Response) {
  if (response.status >= 200 && response.status < 400) {
    return response;
  } else {
    console.error(response);
  }
}

/**
 * response转json
 * @param response
 * @returns
 */
function parseJSON(response?: Response) {
  return response?.json();
}

/**
 * json转url参数
 * @param param
 * @param key
 * @returns
 */
function parseParam(param: any, key?: string) {
  let paramStr = "";
  let paramtype = typeof param;
  if (
    paramtype === "string" ||
    paramtype === "number" ||
    paramtype === "boolean"
  ) {
    paramStr += "&" + key + "=" + encodeURIComponent(param);
  } else {
    for (let i in param) {
      let k =
        key == null
          ? i
          : key + (param instanceof Array ? "[" + i + "]" : "." + i);
      paramStr += "&" + parseParam(param[i], k);
    }
  }
  return paramStr.substr(1);
}

/**
 * json转formData
 * @param formData
 * @param param
 * @param key
 * @returns
 */
function parseFormData(param: any, formData?: FormData, key?: string): any {
  let paramtype = typeof param;
  if (formData) {
    if (
      paramtype === "string" ||
      paramtype === "number" ||
      paramtype === "boolean"
    ) {
      formData.append(key || "formData", param);
    } else {
      for (let i in param) {
        let k =
          key == null
            ? i
            : key + (param instanceof Array ? "[" + i + "]" : "." + i);
        formData = parseFormData(formData, param[i], k);
      }
    }
    return formData;
  } else {
    let data = "";
    for (let i in param) {
      let k =
        key == null
          ? i
          : key + (param instanceof Array ? "[" + i + "]" : "." + i);
      data += `&${k}=${param[i]}`;
    }
    return data;
  }
}

/**
 * get访问
 */
function get(url: string, data: any, contentType?: string, headers?: any) {
  if (typeof url === "undefined" && url === null && url === "") {
    return Promise.reject();
  }
  if (data !== null && typeof data === "object") {
    url += "?" + parseParam(data);
  }
  return fetchRequest("GET", url, null, contentType, headers);
}

/**
 * post提交请求
 */
function post(url: string, data: any, contentType?: string, headers?: any) {
  if (typeof url === "undefined" && url === null && url === "") {
    return Promise.reject();
  }
  if (
    !(data instanceof FormData) &&
    data !== null &&
    typeof data === "object"
  ) {
    data = parseFormData(data);
  }
  return fetchRequest("POST", url, data, contentType, headers);
}

/**
 * put提交请求参数是一个对象
 */
function put(url: string, data: any) {
  if (typeof url === "undefined" && url === null && url === "") {
    return Promise.reject();
  }
  if (data !== null && typeof data === "object") {
    data = JSON.stringify(data);
  }
  return fetchRequest("PUT", url, data, "application/json");
}

/**
 * 提交删除请求
 */
function del(url: string, data: any) {
  if (typeof url === "undefined" && url === null && url === "") {
    return Promise.reject();
  }
  return fetchRequest("DELETE", url, null);
}

/**
 * fetch请求
 */
function fetchRequest(
  method: string,
  url: string,
  data: any,
  contentType?: string,
  headers?: any
) {
  if (typeof url === "undefined" && url === null && url === "") {
    return Promise.reject();
  }

  if (typeof method === "undefined" && method === null && method === "") {
    return Promise.reject();
  }

  method = method.toUpperCase(); //转成全大写

  let requestData: any = {
    method: method,
    //credentials: 'same-origin' //同域中自动发送cookie,加上 credentials 的 same-origin选项。否则，Cookie将不会被发送，导致这些请求不保留认证会话。
    credentials: "include", //对于CORS请求，使用include值允许将凭据发送到其他域
  };

  if (typeof data !== "undefined" && data !== null) {
    requestData["body"] = data;
  }

  if (typeof contentType !== "undefined" && contentType !== null) {
    requestData["headers"] = { "Content-Type": contentType };
  }

  if (typeof headers !== "undefined" && headers !== null) {
    requestData["headers"] = {
      ...(requestData["headers"] || {}),
      ...(headers || {}),
    };
  }

  try {
    return fetch(url, requestData).then(checkStatus).then(parseJSON);
  } catch (error) {
    return Promise.reject(error);
  }
}

export default {
  get,
  post,
  put,
  del,
};
